﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
/// <summary>
/// 自动给资源文件添加标记
/// 
/// Description:
///     开发思路
///         1： 定位需要打包资源文件根目录
///         2： 遍历每个"场景"文件夹(目录)
///                 A：遍历本场景目录下所有的目录或者文件
///                    如果是目录，则继续"递归"访问里面的文件，直到定位到文件
///                 B：找到文件，则使用AssetImporter类，标记"包名"与"后缀名"
/// 
/// </summary>

namespace ABFW
{
    public class AutoSetLabels
    {
        //设置AB包名
        [MenuItem("AssetBundleTools/Set AB Label")]
        public static void SetABLabel()
        {
            //定义需要打包资源的文件夹根目录
            string strNeedSetLabelRoot = string.Empty;
            //目录信息(场景目录信息数组,表示所有的根目录下场景目录)
            DirectoryInfo[] dirScenesDIRArray = null;

            //清空无用AB标记
            AssetDatabase.RemoveUnusedAssetBundleNames();
            //需要打包资源的文件夹根目录
            //Application.dataPath 即Asset的目录
            //strNeedSetLabelRoot = Application.dataPath + "/" + "AB_Res";
            strNeedSetLabelRoot = PathTools.GetABResourcesPath();

            //获取文件夹信息
            DirectoryInfo dirTempInfo = new DirectoryInfo(strNeedSetLabelRoot);
            dirScenesDIRArray = dirTempInfo.GetDirectories();

            //2： 遍历每个场景文件夹(目录)
            foreach(DirectoryInfo currentDIR in dirScenesDIRArray)
            {
                //2.1 遍历本场景目录下所有的目录或者文件
                //如果是目录,则继续"递归"访问里面的文件,直到定位到文件
                string tmpScenesDIR = strNeedSetLabelRoot + "/" + currentDIR.Name; //全路径
                DirectoryInfo tmpScenesDIRInfo = new DirectoryInfo(tmpScenesDIR);
                int tmpIndex = tmpScenesDIR.LastIndexOf("/");
                string tmpScenesName = tmpScenesDIR.Substring(tmpIndex+1);  //场景名称
                //2.2递归调用方法,找到文件,则使用AssetImporter类，标记包名和后缀名
                JudgeDIRorFileByRecursive(currentDIR, tmpScenesName);
            }

            AssetDatabase.Refresh();
            Debug.Log("本次设置标记完成");
        }

        /// <summary>
        /// 递归判断是否为目录与文件,修改AssetBundle的标记(label)
        /// </summary>
        /// <param name="currentDIR">当前文件信息(文件与目录信息可以互相转换)</param>
        /// <param name="scenesName">当前场景名称</param>
        private static void JudgeDIRorFileByRecursive(FileSystemInfo fileSysInfo,string scenesName)
        {
            //调试信息
            //Debug.Log("currentDIR.name=" + currentDIR.Name);
            //Debug.Log("scenesName.name=" + scenesName);
            //参数检查
            if (!fileSysInfo.Exists)
            {
                Debug.LogError("文件或者目录名称：" + fileSysInfo + "不存在,请检查");
                return;
            }

            DirectoryInfo dirInfoObj = fileSysInfo as DirectoryInfo; //文件信息转换为目录信息
            FileSystemInfo[] fileSysArray = dirInfoObj.GetFileSystemInfos();
            
            foreach (FileSystemInfo fileInfo in fileSysArray)
            {
                FileInfo fileInfoObj = fileInfo as FileInfo;
                //文件类型
                if (fileInfoObj != null)
                {
                    //修改文件的AssetBundle标签
                    SetFileABLabel(fileInfoObj, scenesName);
                }
                //目录类型
                else
                {
                    //如果是目录则递归调用
                    JudgeDIRorFileByRecursive(fileInfo,scenesName);
                }
            }

        }

        /// <summary>
        /// 对指定的文件设置"AB包名称"
        /// </summary>
        /// <param name="fileInfoObj">文件信息</param>
        /// <param name="scenesName">场景名称</param>
        private static void SetFileABLabel(FileInfo fileInfoObj,string scenesName)
        {
            //Debug.Log("fileInfoObj="+fileInfoObj.Name);
            //Debug.Log("scenesName=" + scenesName);
            //FULLNAME是文件的绝对路径
            //Debug.Log("fileInfoObj="+fileInfoObj.FullName);

            //AssetBundle 包名称
            string strABName = string.Empty;
            //文件路径(相对路径)
            string strAssetFilePath = string.Empty;

            //参数检查(*.meta文件不作任何处理)
            if (fileInfoObj.Extension == ".meta") return;
            //得到AB包名称
            strABName = GetABName(fileInfoObj,scenesName);
            //获取资源文件相对路径,只要绝对路径中的相对路径
            int tmpIndex = fileInfoObj.FullName.IndexOf("Assets");
            strAssetFilePath = fileInfoObj.FullName.Substring(tmpIndex);

            //给资源文件设置AB名称以及后缀
            AssetImporter tmpImporterObj = AssetImporter.GetAtPath(strAssetFilePath);
            tmpImporterObj.assetBundleName = strABName;

            if(fileInfoObj.Extension == ".unity")
            {
                //定义AB包的扩展名
                tmpImporterObj.assetBundleVariant = "u3d";
            }else
            {
                tmpImporterObj.assetBundleVariant = "ab";
            }

        }

        /// <summary>
        /// 设置AB包的名称
        /// </summary>
        /// <param name="fileInfoObj">文件信息</param>
        /// <param name="scenesName">场景名称</param>
        /// AB包的形成规则
        ///     AB包的名称 = "所在二级目录的名称" (场景名称) + "三级目录名称" (下一级的"类型名称")
        /// 
        /// 如 Scene_1/Materials 即BundleName
        /// <returns>
        /// 返回一个合法的AB包的名称
        /// </returns>
        private static string GetABName(FileInfo fileInfoObj,string scenesName)
        {

            //Debug.Log(fileInfoObj.FullName);

            string strABName = string.Empty;

            //全路径(Windows格式)
            string tmpWinPath = fileInfoObj.FullName;

            //Unity路径
            //替换为Unity字符串分隔符
            string tmpUnityPath = tmpWinPath.Replace("\\","/");
            //定位"场景名称" 后面字符位置
            int tmpSceneNamePosition = tmpUnityPath.IndexOf(scenesName) + scenesName.Length;
            //AB包中"类型名称"所在区域
            string strABFileNameArea = tmpUnityPath.Substring(tmpSceneNamePosition + 1);
            //测试
            //Debug.Log("@@@strABFileNameArea: " + strABFileNameArea);
            if (strABFileNameArea.Contains("/"))
            {
                string[] tmpStrArray = strABFileNameArea.Split('/');
                //AB包名称正式形成
                strABName = scenesName + "/" + tmpStrArray[0];
            }else
            {
                //定义*.Unity文件形成的特殊AB包的名称
                strABName = scenesName + "/" + scenesName;
            }

            return strABName;
        }


    }//Class_End
}

